package com.fqgj.sentry.biz.pc;

import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.sentry.biz.pc.vo.policyexecutor.PolicyExecutorCurrentVo;
import com.fqgj.sentry.biz.pc.vo.policyexecutor.PolicyExecutorHistoryVo;
import com.fqgj.sentry.biz.pc.vo.policyexecutor.PolicyExecutorPendingVo;
import com.fqgj.sentry.biz.pc.vo.policyexecutor.PolicyExecutorVo;
import com.fqgj.sentry.common.cache.RequestLocalInfo;
import com.fqgj.sentry.common.redis.RedisUtil;
import com.fqgj.sentry.controller.pc.request.AddPolicyExecutorVo;
import com.fqgj.sentry.controller.pc.request.ExecutorComboVo;
import com.fqgj.sentry.controller.pc.request.UpdateExecutorInfoVo;
import com.fqgj.sentry.manage.entity.McMerchantEntity;
import com.fqgj.sentry.manage.service.ApplicationService;
import com.fqgj.sentry.policy.client.EventService;
import com.fqgj.sentry.policy.client.PolicyExecutorService;
import com.fqgj.sentry.policy.client.PolicyService;
import com.fqgj.sentry.policy.client.PolicySetService;
import com.fqgj.sentry.policy.entity.PcEventEntity;
import com.fqgj.sentry.policy.entity.PcExecutorEntity;
import com.fqgj.sentry.policy.entity.PcPolicyEntity;
import com.fqgj.sentry.policy.entity.PcPolicySetsEntity;
import com.fqgj.sentry.policy.enums.ActiveEnum;
import com.fqgj.sentry.policy.enums.ExecutorTypeEnum;
import com.fqgj.sentry.policy.enums.VersionStatusEnum;
import com.fqgj.log.interfaces.Log;
import com.fqgj.log.factory.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Created by ykpbean kangping.ying@yuntu-inc.com
 *
 * @description
 * @create 2017-07-27 下午5:19
 */

@Component
public class PolicyExecutorBusiness {
    public static final Log LOGGER = LogFactory.getLog(PolicyExecutorBusiness.class);


    @Autowired
    private PolicyExecutorService policyExecutorService;
    @Autowired
    private PolicyService policyService;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private PolicySetService policySetService;
    @Autowired
    private ApplicationService applicationService;
    @Autowired
    private EventService eventService;


    /**
     * 新增执行者
     *
     * @param addPolicyExecutorVo
     * @return
     */
    public PolicyExecutorPendingVo addPolicyExecutor(AddPolicyExecutorVo addPolicyExecutorVo) {
        PcExecutorEntity executorEntity = new PcExecutorEntity()
                .setCopyType(addPolicyExecutorVo.getCopyType())
                .setInfo(addPolicyExecutorVo.getInfo())
                .setCopyVersion(addPolicyExecutorVo.getCopyVersion())
                .setIsActive(ActiveEnum.close.getType()).setPolicySetsId(addPolicyExecutorVo.getPolicySetsId())
                .setType(addPolicyExecutorVo.getType())
                .setVersionStatus(VersionStatusEnum.pending_version.getStatus());
        Long executorId = policyExecutorService.insertPolicyExecutor(executorEntity);
        if (addPolicyExecutorVo.getCopyExecutorId() != null) {
            policyExecutorService.copyPolicyExecutor(addPolicyExecutorVo.getCopyExecutorId(), executorId);
        }
        PolicyExecutorPendingVo pendingVo = new PolicyExecutorPendingVo()
                .setId(executorId).setPolicySetsId(addPolicyExecutorVo.getPolicySetsId())
                .setType(addPolicyExecutorVo.getType());
        return pendingVo;
    }

    /**
     * 执行者 列表
     *
     * @param policySetsId
     * @return
     */
    public Map<String, PolicyExecutorVo> queryEachTypeExecutor(Long policySetsId) {
        LinkedHashMap<String, PolicyExecutorVo> executorVoHashMap = new LinkedHashMap<>();
        executorVoHashMap.put("championExecutor", getPolicyExecutorByType(policySetsId, ExecutorTypeEnum.champion.getType()));
        executorVoHashMap.put("challengerExecutor", getPolicyExecutorByType(policySetsId, ExecutorTypeEnum.challenger.getType()));
        executorVoHashMap.put("verifierExecutor", getPolicyExecutorByType(policySetsId, ExecutorTypeEnum.verifier.getType()));
        return executorVoHashMap;
    }

    /**
     * 执行者 删除
     *
     * @param executorId
     * @return
     */
    public Boolean delPolicyExecutor(Long executorId) {
        return policyExecutorService.deletePolicyExecutor(executorId);
    }

    /**
     * 更新 执行者
     *
     * @param updateExecutorInfoVo
     * @return
     */
    public Boolean updatePolicyExecutorInfo(UpdateExecutorInfoVo updateExecutorInfoVo) {
        return policyExecutorService.updatePolicyExecutorInfo(updateExecutorInfoVo.getExecutorId(), updateExecutorInfoVo.getExecutorInfo());
    }

    /**
     * 丢弃待发布 版本
     *
     * @param executorId
     * @return
     */
    public Boolean dropPolicyExecutor(Long executorId) {
        return policyExecutorService.dropPolicyExecutor(executorId);
    }


    /**
     * 设置执行者开关
     *
     * @param executorId
     * @param open
     * @return
     */
    public Boolean setExecutorSwitch(Long executorId, Boolean open) {
        Integer isOpen = 0;
        if (open) {
            isOpen = 1;
        }
        return policyExecutorService.setExecutorSwitch(executorId, isOpen);
    }

    /**
     * 设置执行者  占比
     *
     * @param executorId
     * @param percent
     * @return
     */
    public Boolean setChallengerExecutorPercent(Long executorId, Integer percent) {
        return policyExecutorService.setChallengerExecutorPercent(executorId, percent);
    }

    /**
     * 版本 回滚
     *
     * @param executorId
     * @return
     */
    public Boolean rollBackExecutor(Long executorId) {
        //清除redis  清除 线上版本
        deleteRedis(executorId);
        return policyExecutorService.rollBackExecutor(executorId);
    }

    /**
     * 清除 Redis
     */
    public void deleteRedis(Long executorId) {
        //清除redis
        try {
            LOGGER.info("executorId:{}开始清理缓存", executorId);
            McMerchantEntity merchantEntity = applicationService.selectByMerchantId(RequestLocalInfo.getCurrentMerchantId());
            LOGGER.info("商户code:{}开始清理缓存", merchantEntity.getCode());
            PcExecutorEntity executorEntity = policyExecutorService.selectByExecutorId(executorId);
            PcPolicySetsEntity policySetsEntity = policySetService.selectOneById(executorEntity.getPolicySetsId());
            PcEventEntity eventEntity = eventService.selectEvent(policySetsEntity.getEventId());
            PcExecutorEntity onLineExecutor = policyExecutorService.selectPcExecutorCurrent(policySetsEntity.getId(), executorEntity.getType(), ActiveEnum.active.getType());
            String key = RedisUtil.getKey(merchantEntity.getCode(), RequestLocalInfo.getCurrentAppCode(), eventEntity.getCode(), executorId);
            String key2 = RedisUtil.getModuleKey(merchantEntity.getCode(), RequestLocalInfo.getCurrentAppCode(), eventEntity.getCode());
            if (redisClient.get(key) != null) {
                LOGGER.error("executorId:{},缓存key:{}", executorId, key);
                redisClient.del(key);
                redisClient.del(key2);
            }
            if (onLineExecutor != null) {
                String onLineKey = RedisUtil.getKey(merchantEntity.getCode(), RequestLocalInfo.getCurrentAppCode(), eventEntity.getCode(), onLineExecutor.getId());
                String onLineKey2 = RedisUtil.getModuleKey(merchantEntity.getCode(), RequestLocalInfo.getCurrentAppCode(), eventEntity.getCode());
                if (redisClient.get(onLineKey) != null) {
                    LOGGER.error("executorId:{},缓存key:{}", onLineExecutor.getId(), onLineKey);
                    redisClient.del(onLineKey);
                    redisClient.del(onLineKey2);
                }
            }
        } catch (Exception e) {
            LOGGER.error(" 缓存清理异常e:{},executorId:{}", e, executorId);
        }
    }

    /**
     * 执行者 发布
     *
     * @param executorId
     * @return
     */
    public Boolean releaseExecutor(Long executorId) {
        LOGGER.info("executorId:{}开始发布", executorId);
        //清除redis  清除 线上版本
        deleteRedis(executorId);
        return policyExecutorService.releaseExecutor(executorId);
    }


    public List<PolicyExecutorHistoryVo> queryExecutorCombo(ExecutorComboVo executorComboVo) {
        List<PcExecutorEntity> pcExecutorEntities = policyExecutorService
                .selectPcExecutorHistoryList(executorComboVo.getPolicySetsId(), executorComboVo.getType());
        List<PolicyExecutorHistoryVo> policyExecutorHistoryVoList = new ArrayList<>();
        for (PcExecutorEntity executorEntity : pcExecutorEntities) {
            PolicyExecutorHistoryVo policyExecutorHistoryVo = new PolicyExecutorHistoryVo();
            BeanUtils.copyProperties(executorEntity, policyExecutorHistoryVo);
            policyExecutorHistoryVoList.add(policyExecutorHistoryVo);
        }
        return policyExecutorHistoryVoList;
    }


    private PolicyExecutorVo getPolicyExecutorByType(Long policySetsId, Integer type) {
        PolicyExecutorVo policyExecutorVo = new PolicyExecutorVo();
        //当前执行者
        PcExecutorEntity pcExecutorEntity = policyExecutorService.selectPcExecutorCurrent(policySetsId, type, ActiveEnum.all.getType());
        if (pcExecutorEntity != null) {
            policyExecutorVo.setExecutorId(pcExecutorEntity.getId());

            PolicyExecutorCurrentVo policyExecutorCurrentVo = new PolicyExecutorCurrentVo();
            BeanUtils.copyProperties(pcExecutorEntity, policyExecutorCurrentVo);
            List<PcPolicyEntity> policyEntityList = policyService
                    .selectPolicyByExecutorId(policyExecutorCurrentVo.getId());
            if (CollectionUtils.isNotEmpty(policyEntityList)) {
                //设置策略集数量
                policyExecutorCurrentVo.setPolicyCount(policyEntityList.size());
            } else {
                policyExecutorCurrentVo.setPolicyCount(0);
            }
            policyExecutorVo.setPolicyExecutorCurrent(policyExecutorCurrentVo);
        }
        //历史执行者
        List<PcExecutorEntity> pcExecutorEntities = policyExecutorService
                .selectPcExecutorHistoryList(policySetsId, type);
        List<PolicyExecutorHistoryVo> policyExecutorHistoryVoList = new ArrayList<>();
        for (PcExecutorEntity executorEntity : pcExecutorEntities) {
            if (executorEntity.getVersionStatus() == 3) {
                PolicyExecutorHistoryVo policyExecutorHistoryVo = new PolicyExecutorHistoryVo();
                BeanUtils.copyProperties(executorEntity, policyExecutorHistoryVo);
                String info = executorEntity.getInfo();
                policyExecutorHistoryVo.setInfo(info);
                if (executorEntity.getPublishDate() != null) {
                    policyExecutorHistoryVo.setPublishDate(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(executorEntity.getPublishDate()));
                }
                policyExecutorHistoryVo.setStatus(executorEntity.getVersionStatus());
                policyExecutorHistoryVoList.add(policyExecutorHistoryVo);
            }

        }
        policyExecutorVo.setPolicyExecutorHistoryList(policyExecutorHistoryVoList);
        //待发布执行者
        PcExecutorEntity entity = policyExecutorService.selectPcExecutorPending(policySetsId, type);
        if (entity != null) {
            PolicyExecutorPendingVo policyExecutorPendingVo = new PolicyExecutorPendingVo();
            BeanUtils.copyProperties(entity, policyExecutorPendingVo);
            policyExecutorVo.setPolicyExecutorPending(policyExecutorPendingVo);
        }
        return policyExecutorVo;
    }


}
